package com.github.data_manage.util

import com.fasterxml.jackson.core.type.TypeReference
import com.github.data_manage.config.BeanConfig
import com.github.data_manage.domain.dto.ContrastIndexDto
import com.github.data_manage.domain.dto.PersonRelationDto
import com.github.data_manage.domain.po.CumulativeInfo
import com.github.data_manage.domain.po.ExposureInfo
import com.github.data_manage.domain.po.FundInternalScore
import jakarta.persistence.AttributeConverter
import jakarta.persistence.Converter
import org.springframework.util.StringUtils

/**
 *@author CHN
 *@since 2024-08-08 21:07
 */
abstract class BaseJpaJsonConverter<T> : AttributeConverter<T, String> {

    override fun convertToDatabaseColumn(attribute: T?): String? {
        return attribute?.let { BeanConfig.objectMapper.writeValueAsString(it) }
    }

    override fun convertToEntityAttribute(dbData: String?): T? {
        if (!StringUtils.hasText(dbData)) {
            return null
        }
        return BeanConfig.objectMapper.readValue(
            dbData,
            entityType()
        )!!
    }

    abstract fun entityType(): TypeReference<T>


}

@Converter
class JpaPersonRelationJsonConverter : AttributeConverter<Collection<PersonRelationDto>, String> {

    override fun convertToDatabaseColumn(attribute: Collection<PersonRelationDto>?): String? {
        return attribute?.let { BeanConfig.objectMapper.writeValueAsString(it) }
    }

    override fun convertToEntityAttribute(dbData: String?): Collection<PersonRelationDto>? {
        return dbData?.let {
            return@let BeanConfig.objectMapper.readValue(
                dbData,
                object : TypeReference<Collection<PersonRelationDto>>() {})
        }
    }
}

@Converter
class JpaFundContrastIndexJsonConverter : AttributeConverter<List<ContrastIndexDto>, String> {

    override fun convertToEntityAttribute(dbData: String?): List<ContrastIndexDto>? {
        return dbData?.let {
            return@let BeanConfig.objectMapper.readValue(
                dbData,
                object : TypeReference<List<ContrastIndexDto>>() {})
        }
    }

    override fun convertToDatabaseColumn(attribute: List<ContrastIndexDto>?): String? {
        return attribute?.let { BeanConfig.objectMapper.writeValueAsString(it) }
    }
}

@Converter
class ListStringJsonConverter : AttributeConverter<List<String>, String> {

    override fun convertToEntityAttribute(dbData: String?): List<String>? {
        return dbData?.let {
            return@let BeanConfig.objectMapper.readValue(
                dbData,
                object : TypeReference<List<String>>() {})
        }
    }

    override fun convertToDatabaseColumn(attribute: List<String>?): String? {
        return attribute?.let { BeanConfig.objectMapper.writeValueAsString(it) }
    }
}


@Converter
class JpaFundInternalScoreJsonConverter : AttributeConverter<FundInternalScore, String> {

    override fun convertToDatabaseColumn(attribute: FundInternalScore): String? {
        return BeanConfig.objectMapper.writeValueAsString(attribute)
    }

    override fun convertToEntityAttribute(dbData: String): FundInternalScore {
        return BeanConfig.objectMapper.readValue(
            dbData,
            FundInternalScore::class.java
        )!!
    }
}

@Converter
class JpaExposureInfoJsonConverter : AttributeConverter<ExposureInfo?, String> {

    override fun convertToDatabaseColumn(attribute: ExposureInfo?): String? {
        if (attribute == null) return null
        return BeanConfig.objectMapper.writeValueAsString(attribute)
    }

    override fun convertToEntityAttribute(dbData: String?): ExposureInfo? {
        if (!StringUtils.hasText(dbData)) {
            return null
        }
        return BeanConfig.objectMapper.readValue(
            dbData,
            ExposureInfo::class.java
        )!!
    }
}

@Converter
class JpaCumulativeInfoJsonConverter : AttributeConverter<CumulativeInfo?, String> {

    override fun convertToDatabaseColumn(attribute: CumulativeInfo?): String? {
        if (attribute == null) return null
        return BeanConfig.objectMapper.writeValueAsString(attribute)
    }

    override fun convertToEntityAttribute(dbData: String?): CumulativeInfo? {
        if (!StringUtils.hasText(dbData)) {
            return null
        }
        return BeanConfig.objectMapper.readValue(
            dbData,
            CumulativeInfo::class.java
        )!!
    }
}

